package com.filldream.fastboot.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.filldream.fastboot.base.entity.SysLog;
import com.filldream.fastboot.base.mapper.SysLogMapper;
import com.filldream.fastboot.base.request.pc.sysLog.SysLogPageSTO;
import com.filldream.fastboot.base.response.app.AccountManagerDTO;
import com.filldream.fastboot.base.response.pc.SystemLoginDTO;
import com.filldream.fastboot.common.annotation.Log;
import com.filldream.fastboot.common.constant.FinalStr;
import com.filldream.fastboot.common.entity.B;
import com.filldream.fastboot.common.entity.P;
import com.filldream.fastboot.common.util.RequestContext;
import com.filldream.fastboot.core.LoginHolder;
import com.filldream.fastboot.core.service.SysLogService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

/**
 * @author RickSun
 * @description 系统日志impl
 * @date 2021/11/16 15:40
 * @return
 **/
@Service
@Transactional(rollbackFor = Exception.class)
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements SysLogService {

    @Override
    public void save( ProceedingJoinPoint joinPoint, SysLog log ) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log aopLog = method.getAnnotation(Log.class);

        // 方法路径
        String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";

        // 描述
        if (log != null) {
            log.setDescription(aopLog.value());
            log.setResourceType( aopLog.type() );
        }
        assert log != null;

        String params;

        HttpServletRequest request = RequestContext.getRequest();

        log.setMethodType( request.getMethod() );

        //获取请求参数
        if( request.getMethod().equals("GET") ){
            params = request.getQueryString();
        }else{
            params = RequestContext.getParameter(method, joinPoint.getArgs());
        }

        //获取请求人昵称
        if( aopLog.type() == 1 ){
            SystemLoginDTO pcUser = LoginHolder.getPcUserOrNull();
            log.setUsername(pcUser != null ? pcUser.getUsername() : "未知" );
            log.setLinkId(pcUser != null ? pcUser.getLinkId() : -1L);
        }else{
            AccountManagerDTO account = LoginHolder.getUserInfoOrNull();
            log.setUsername(account != null ? account.getNickname() : "未知" );
            log.setLinkId(-1L);
        }

        //其他
        log.setRequestIp(RequestContext.getIp2());
        log.setAddress("待定"); //有需要的可以使用第三方解析IP
        log.setMethod(methodName);
        log.setParams(params);
        log.setBrowser(RequestContext.getUserAgentStr());
        log.setRequestId( MDC.get(FinalStr.requestId) );
        log.setCreateTime(new Date());
        save(log);
    }

    @Override
    public P<SysLog> page(SysLogPageSTO sysLogPageSTO) {

        QueryWrapper<SysLog> sql = new QueryWrapper<>();

        SystemLoginDTO pcUser = LoginHolder.getPcUser();
        if( !pcUser.getRoleId().equals(1L) ){
            sql.eq("link_id",pcUser.getLinkId());
        }

        if( sysLogPageSTO.getResourceType() != null ){
            sql.eq("resource_type",sysLogPageSTO.getResourceType());
        }

        if( sysLogPageSTO.getLogType() != null ){
            sql.eq("log_type",sysLogPageSTO.getLogType());
        }

        if( sysLogPageSTO.getCreateTimeStart() != null ){
            sql.ge("create_time",sysLogPageSTO.getCreateTimeStart());
        }

        sql.le("create_time",sysLogPageSTO.getCreateTimeEnd());

        String keyContent = sysLogPageSTO.getKeyContent();
        if(StringUtils.isNotEmpty( keyContent )){
            sql.and(eq -> eq
                    .like("description",keyContent)
                    .or().like("username",keyContent)
                    .or().like("method",keyContent)
                    .or().like("request_id",keyContent))
            ;
        }

        sql.orderByDesc("create_time");

        Page<SysLog> page = page(sysLogPageSTO.page(), sql);
        List<SysLog> records = page.getRecords();
        for (SysLog item : records) {
            item.setParams("");
            item.setExceptionDetail("");
        }

        return P.autoSuccess(page);
    }

    @Override
    public B clear(Long linkId) {
        LambdaQueryWrapper<SysLog> sql = new LambdaQueryWrapper<>();
        if( !LoginHolder.getPcUser().getRoleId().equals(1L) ){
            sql.eq(SysLog::getLinkId, LoginHolder.getPcUser().getLinkId() );
        }
        baseMapper.delete(sql);
        return B.success();
    }

}